package com.aura.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.DocWriteResponse.Result;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.support.replication.ReplicationResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.Settings.Builder;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;

/**
 * 参考链接：
 * https://blog.csdn.net/weixin_39860704/article/details/89497547
 * https://www.cnblogs.com/betterwgo/p/11268869.html
 */
public class EsUtils {
	public static void main(String[] args) {
		RestHighLevelClient client = getClient();
		CreateIndexRequest request = createIndex("twitter",client);
		createMapping(request);
		setOuttimes(request);
		
		//同步执行，执行请求，创建索引
//		CreateIndexResponse createIndexResponse = null;
//		try {
//			createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//		boolean acknowledged = createIndexResponse.isAcknowledged(); 
//		boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();
//	    System.out.println("acknowledged="+acknowledged);
//	    System.out.println("shardsAcknowledged="+shardsAcknowledged);
	   
	    //删除索引
	    //deleteIndex("twitter",client);
	    
		//修改表结构
	    try {
	    	updateMapping("twitter",client);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
		//创建Document
		//createDocument("twitter",client);
		
		//查询Document通过id
		//getDocumentById("twitter","1",client);
		
		//修改Document通过id
		//updateDocumentById("twitter","1",client);
		
		//删除Document通过id
		//removeDocumentById("twitter","1",client);
		//关闭链接
	    try {
			client.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	//获取连接
	public static RestHighLevelClient getClient() {
		RestHighLevelClient client = new RestHighLevelClient(
				RestClient.builder(new HttpHost("localhost", 9200, "http")));

		return client;
	}
	
	//创建索引(即创建库)
	public static CreateIndexRequest createIndex(String indexName,RestHighLevelClient client){
		//1. 创建索引请求
		CreateIndexRequest request = new CreateIndexRequest(indexName);
		Builder builder = Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 1);
		request.settings(builder);
		return request;
	}
	
	//删除索引
	public static void deleteIndex(String indexName,RestHighLevelClient client) {
		DeleteIndexRequest request = new DeleteIndexRequest(indexName);
		AcknowledgedResponse deleteIndexResponse = null;
		try {
			deleteIndexResponse = client.indices().delete(request, RequestOptions.DEFAULT);
		} catch (IOException e) {
			e.printStackTrace();
		}
		boolean acknowledged = deleteIndexResponse.isAcknowledged();
		System.out.println("index删除结果:"+acknowledged);
	}
	
	 /**
     * 判断索引是否存在
     * @param indexName
     * @return
     * @throws IOException
     */
    public boolean checkIndexExists(String indexName,RestHighLevelClient client) {
        GetIndexRequest request = new GetIndexRequest(indexName);
        try {
            return client.indices().exists(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
           System.out.println("判断索引是否存在，操作异常！");
        }
        return false;
    }
	
	//设置mapping(即创建表结构)
	public static void createMapping(CreateIndexRequest request){
		Map<String, Object> message = new HashMap<>();
		message.put("type", "text");
		Map<String, Object> properties = new HashMap<>();
		properties.put("message", message);
		Map<String, Object> mapping = new HashMap<>();
		mapping.put("properties", properties);
		request.mapping(mapping);
	}
	
	//更新mapping(更新表结构)
	public static void updateMapping(String indexName,RestHighLevelClient client) throws Exception {
		PutMappingRequest request = new PutMappingRequest(indexName);
		
		XContentBuilder builder = XContentFactory.jsonBuilder();
		builder.startObject();
		{
		    builder.startObject("properties");
		    {
		        builder.startObject("message");
		        {
		            builder.field("type", "text");
		        }
		        builder.endObject();
		        
		        builder.startObject("username");
		        {
		            builder.field("type", "text");
		        }
		        builder.endObject();
		        
		        builder.startObject("sex");
		        {
		            builder.field("type", "text");
		        }
		        builder.endObject();
		    }
		    builder.endObject();
		}
		builder.endObject();
		
		request.source(builder);
		AcknowledgedResponse PutMappingResponse = client.indices().putMapping(request, RequestOptions.DEFAULT);
		boolean acknowledged = PutMappingResponse.isAcknowledged();
		System.out.println("updateMapping结果:"+acknowledged);
	}
	
	//新增Document
	public static void createDocument(String indextName,RestHighLevelClient client){
        // 1、创建索引请求
        IndexRequest request = new IndexRequest(
        		indextName,   //索引
                "_doc",     // mapping type
                "2");     //文档id  
        
        // 2、准备文档数据
        // 方式一：直接给JSON串
        String jsonString = "{" +
                "\"username\":\"张三\"," +
                "\"sex\":\"男\"," +
                "\"message\":\"你好啊，hello!\"" +
                "}";
        request.source(jsonString, XContentType.JSON); 
        
        // 方式二：以map对象来表示文档
        /*
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("username", "张三");
        jsonMap.put("message", "你好啊，hello!");
        request.source(jsonMap); 
        */
        
        // 方式三：用XContentBuilder来构建文档
        /*
        XContentBuilder builder = XContentFactory.jsonBuilder();
        builder.startObject();
        {
            builder.field("username", "张三");
            builder.field("message", "你好啊，hello!");
        }
        builder.endObject();
        request.source(builder); 
        */
        
        // 方式四：直接用key-value对给出
        /*
        request.source("username", "张三",
                        "message", "你好啊，hello!");
        */
        
        //3、其他的一些可选设置
        /*
        request.routing("routing");  //设置routing值
        request.timeout(TimeValue.timeValueSeconds(1));  //设置主分片等待时长
        request.setRefreshPolicy("wait_for");  //设置重刷新策略
        request.version(2);  //设置版本号
        request.opType(DocWriteRequest.OpType.CREATE);  //操作类别  
        */
        
        //4、发送请求
        IndexResponse indexResponse = null;
        try {
            // 同步方式
            indexResponse = client.index(request,RequestOptions.DEFAULT);            
        } catch(Exception e) {
           System.out.println("索引异常:"+e);
        }
        
        //5、处理响应
        if(indexResponse != null) {
            String index = indexResponse.getIndex();
            String type = indexResponse.getType();
            String id = indexResponse.getId();
            long version = indexResponse.getVersion();
            if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
                System.out.println("新增文档成功，处理逻辑代码写到这里。");
            } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
                System.out.println("修改文档成功，处理逻辑代码写到这里。");
            }
            // 分片处理信息
            ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
            if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
                
            }
            // 如果有分片副本失败，可以获得失败原因信息
            if (shardInfo.getFailed() > 0) {
                for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
                    String reason = failure.reason(); 
                    System.out.println("副本失败原因：" + reason);
                }
            }
        }
        
        
        //异步方式发送索引请求
        /*ActionListener<IndexResponse> listener = new ActionListener<IndexResponse>() {
            @Override
            public void onResponse(IndexResponse indexResponse) {
                
            }
            @Override
            public void onFailure(Exception e) {
                
            }
        };
        client.indexAsync(request, listener);
        */
	}
	
	//更新Document通过id
	public static void updateDocumentById(String indexName,String id,RestHighLevelClient client){
	  Map<String,Object> map=new HashMap<>();
      map.put("username", "李四");
      UpdateRequest updateRequest = new UpdateRequest(indexName,id).doc(map);
      try {
		UpdateResponse updateResponse= client.update(updateRequest,RequestOptions.DEFAULT);
	} catch (IOException e) {
		System.out.println("updateResponse异常:"+e);
	}
  	System.out.println("updateDocumentById完成");
	}
	
	//删除Document通过id
	public static String removeDocumentById(String indexName,String id,RestHighLevelClient client) {
        DeleteRequest deleteRequest = new DeleteRequest(indexName, id);
        
        // 操作ES
        DeleteResponse deleteResponse = null;
        try {
            deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            System.out.println("es删除异常："+e);
        }
        Result resultResponse = deleteResponse.getResult();
        String result = resultResponse.toString();
        System.out.println("removeDocumentById结果:"+result);
		return result;
	}
	
	//查询Document
	 public static String getDocumentById(String indexName,String id,RestHighLevelClient client) {
        GetRequest getRequest = new GetRequest(indexName, id);
        GetResponse getResponse = null;
        try {
            getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
         System.out.println("es查询异常:"+e);
        }
        
        String result = getResponse.getSourceAsString();
        System.out.println("getDocumentById结果："+result);
        return result;
	 }
	
	
	//设置超时时间
	public static void setOuttimes(CreateIndexRequest request) {
		request.setTimeout(TimeValue.timeValueMinutes(2));
		request.setMasterTimeout(TimeValue.timeValueMinutes(1));
	}
}